import 'package:json_annotation/json_annotation.dart';

part 'tianyi_user.g.dart';

@JsonSerializable()
class TianyiUser {
  final String? userId;
  final String? nickname;
  final String? avatar;
  final String? phone;
  final String? email;
  final int? totalSpace;
  final int? usedSpace;
  final String? sessionKey;
  final String? sessionSecret;
  final DateTime? loginTime;
  final DateTime? expireTime;
  final bool isLoggedIn;

  TianyiUser({
    this.userId,
    this.nickname,
    this.avatar,
    this.phone,
    this.email,
    this.totalSpace,
    this.usedSpace,
    this.sessionKey,
    this.sessionSecret,
    this.loginTime,
    this.expireTime,
    this.isLoggedIn = false,
  });

  factory TianyiUser.fromJson(Map<String, dynamic> json) =>
      _$TianyiUserFromJson(json);

  Map<String, dynamic> toJson() => _$TianyiUserToJson(this);

  factory TianyiUser.fromMap(Map<String, dynamic> map) {
    return TianyiUser(
      userId: map['user_id'],
      nickname: map['nickname'],
      avatar: map['avatar'],
      phone: map['phone'],
      email: map['email'],
      totalSpace: map['total_space']?.toInt(),
      usedSpace: map['used_space']?.toInt(),
      sessionKey: map['session_key'],
      sessionSecret: map['session_secret'],
      loginTime: map['login_time'] != null
          ? DateTime.parse(map['login_time'])
          : null,
      expireTime: map['expire_time'] != null
          ? DateTime.parse(map['expire_time'])
          : null,
      isLoggedIn: map['is_logged_in'] == 1,
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'user_id': userId,
      'nickname': nickname,
      'avatar': avatar,
      'phone': phone,
      'email': email,
      'total_space': totalSpace,
      'used_space': usedSpace,
      'session_key': sessionKey,
      'session_secret': sessionSecret,
      'login_time': loginTime?.toIso8601String(),
      'expire_time': expireTime?.toIso8601String(),
      'is_logged_in': isLoggedIn ? 1 : 0,
    };
  }

  TianyiUser copyWith({
    String? userId,
    String? nickname,
    String? avatar,
    String? phone,
    String? email,
    int? totalSpace,
    int? usedSpace,
    String? sessionKey,
    String? sessionSecret,
    DateTime? loginTime,
    DateTime? expireTime,
    bool? isLoggedIn,
  }) {
    return TianyiUser(
      userId: userId ?? this.userId,
      nickname: nickname ?? this.nickname,
      avatar: avatar ?? this.avatar,
      phone: phone ?? this.phone,
      email: email ?? this.email,
      totalSpace: totalSpace ?? this.totalSpace,
      usedSpace: usedSpace ?? this.usedSpace,
      sessionKey: sessionKey ?? this.sessionKey,
      sessionSecret: sessionSecret ?? this.sessionSecret,
      loginTime: loginTime ?? this.loginTime,
      expireTime: expireTime ?? this.expireTime,
      isLoggedIn: isLoggedIn ?? this.isLoggedIn,
    );
  }

  double get usagePercentage {
    if (totalSpace == null || totalSpace == 0) return 0.0;
    return (usedSpace ?? 0) / totalSpace! * 100;
  }

  int get freeSpace => (totalSpace ?? 0) - (usedSpace ?? 0);

  bool get isSessionValid {
    if (!isLoggedIn || expireTime == null) return false;
    return DateTime.now().isBefore(expireTime!);
  }

  @override
  String toString() {
    return 'TianyiUser(userId: $userId, nickname: $nickname, avatar: $avatar, phone: $phone, email: $email, totalSpace: $totalSpace, usedSpace: $usedSpace, sessionKey: $sessionKey, sessionSecret: $sessionSecret, loginTime: $loginTime, expireTime: $expireTime, isLoggedIn: $isLoggedIn)';
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is TianyiUser &&
        other.userId == userId &&
        other.nickname == nickname &&
        other.avatar == avatar &&
        other.phone == phone &&
        other.email == email &&
        other.totalSpace == totalSpace &&
        other.usedSpace == usedSpace &&
        other.sessionKey == sessionKey &&
        other.sessionSecret == sessionSecret &&
        other.loginTime == loginTime &&
        other.expireTime == expireTime &&
        other.isLoggedIn == isLoggedIn;
  }

  @override
  int get hashCode {
    return userId.hashCode ^
        nickname.hashCode ^
        avatar.hashCode ^
        phone.hashCode ^
        email.hashCode ^
        totalSpace.hashCode ^
        usedSpace.hashCode ^
        sessionKey.hashCode ^
        sessionSecret.hashCode ^
        loginTime.hashCode ^
        expireTime.hashCode ^
        isLoggedIn.hashCode;
  }
}